#include "plugin_mpl.h"
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include "hilog_wrapper.h"
#include "cashdevice_def.h"

namespace SwanLink {
namespace Finance {

PluginMpl::PluginMpl():
    m_pHandle(nullptr),
    m_pPlg(nullptr),
    m_iStatus(ERR_PLUGIN_UNLOADED) {
}

PluginMpl::~PluginMpl() {
    FreePlugin();
}

void PluginMpl::DestroyAdapter(std::shared_ptr<IAdaptor>&)
{}

bool PluginMpl::LoadPlugin(const std::string& libname)
{
    m_pHandle = dlopen(libname.c_str(), RTLD_NOW);

    if (m_pHandle == nullptr) {
        m_iStatus = ERR_PLUGIN_NOT_EXIST;
        CARDSENDER_HILOGE(CARDSENDER_SRV, "load %{public}s failed", libname.c_str());
        return false;
    }
    GetPluginFunc getPlugin = (GetPluginFunc)dlsym(m_pHandle, "GetPlugin");
    if (getPlugin == nullptr) {
        m_iStatus = ERR_PLUGIN_LOAD_FAILED;
        CARDSENDER_HILOGE(CARDSENDER_SRV, "GetPlugin failed");
        dlclose(m_pHandle);
        m_pHandle = nullptr;
        return false;
    }
    m_pPlg = getPlugin();
    if (m_pPlg == nullptr) {
        m_iStatus = ERR_PLUGIN_LOAD_FAILED;
        CARDSENDER_HILOGE(CARDSENDER_SRV, "GetPlugin failed");
        dlclose(m_pHandle);
        return false;
    }
    m_iStatus = SUCCESS;
    return true;
}

void PluginMpl::FreePlugin()
{
    m_pPlg = nullptr;
    if (m_pHandle) {
        dlclose(m_pHandle);
        m_pHandle = nullptr;
    }
    m_iStatus = ERR_PLUGIN_UNLOADED;
}

std::string PluginMpl::GetName() const
{
    if (m_pPlg)
        return m_pPlg->name;
    return "";
}

bool PluginMpl::GetAccess(ACCESS_MODE mode, const char *dev, DevAccess& access)
{
    if (m_pPlg == nullptr) {
        return false;
    }
    strcpy_s(access.desc, MAX_INFO_LEN, m_pPlg->desc);
    strcpy_s(access.name, MAX_DEV_NAME_LEN, m_pPlg->name);
    access.transport = m_pPlg->GetAccess(mode, dev);
    return true;
}

std::shared_ptr<IAdaptor> PluginMpl::CreateAdaptor()
{
    if (m_pPlg == nullptr) {
        return nullptr;
    }
    return m_pPlg->CreateAdaptor();
}

int  PluginMpl::GetStatus() const
{
    return m_iStatus;
}
}  // namespace Finance
}  // namespace SwanLink
